package io.renren.modules.app.controller;

import java.util.List;

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.renren.modules.app.entity.JobInfoPO;
import io.renren.modules.app.job.commjob.CommonJob;
import io.renren.modules.app.job.commjob.ConcurrentJob;
import io.renren.modules.app.job.commjob.DisallowConcurrentJob;
import io.renren.modules.app.service.JobService;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping(value = "/job")
public class JobController {
	
	@Autowired
	@Qualifier("SchedulerFactoryBean")
	private SchedulerFactoryBean schedulerFactoryBean;
	
	@Autowired
	private JobService jobService;
	
	/**
	 * 根据id手动执行指定job
	 * 
	 * @param id
	 * @return
	 * @throws SchedulerException
	 */
	public String executeJob(@PathVariable String id) throws SchedulerException{
		log.error("servlet execute by id : " + id);
		JobInfoPO po = jobService.queryByJobID(id);
		if(po == null) {
			return "id[" + id + "] job is not exists.";
		}
		boolean rst = new ConcurrentJob().invoke(initJobDataMap(po));
		return rst ? "success" : "fail" ;
	}
	
	/**
	 * 根据ID删除指定的Job
	 * 
	 * @param id
	 * @return
	 * @throws SchedulerException
	 */
	@RequestMapping("/deleteJob/{id}")
	public String deleteJob(@PathVariable String id) throws SchedulerException {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		log.error("servlet deleteJob by id : " + id);
		JobInfoPO po = jobService.queryByJobID(id);
		if(po == null) {
			return "id[" + id + "] job is not exists.";
		}
		JobKey jobKey = new JobKey(po.getName_(), po.getGroup_());
		TriggerKey triggerKey = new TriggerKey(po.getName_(), po.getGroup_());
		scheduler.unscheduleJob(triggerKey);
		scheduler.deleteJob(jobKey);
		jobService.removeJob(id);
		return "success";
	}

	
	/**
	 * 根据ID激活指定的Job
	 * 
	 * @param id
	 * @return
	 * @throws SchedulerException
	 */
	@RequestMapping("/activeJob/{id}")
	public String activeJob(@PathVariable String id) throws SchedulerException {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		log.error("servlet activeJob by id : " + id);
		JobInfoPO po = jobService.queryByJobID(id);
		if(po == null) {
			return "id[" + id + "] job is not exists.";
		}
		try {
			jobService.activeJob(id);
			po = jobService.queryByJobID(id);
			initJob(po);
		} catch (SchedulerException e) {
			log.error("id[" + id + "] activeJob fail.", e);
			return "Error while activeJob " + e.getMessage();
		}
		
		return "success";
	}
	
	/**
	 * 根据ID重启指定Job
	 * 
	 * @param id
	 * @return
	 * @throws SchedulerException
	 */
	@RequestMapping("/refresh/{id}")
	public String refresh(@PathVariable String id) throws SchedulerException {
		JobInfoPO po = jobService.queryByJobID(id);
		try {
			if(po == null) {
				return "id[" + id + "] job is not exists.";
			}
			initJob(po);
		} catch (SchedulerException e) {
			log.error("id[" + id + "] activeJob fail.", e);
			return "Error while Refresh " + e.getMessage();
		}
		return "success";
	}
	
	/**
	 * 重启数据库中所有的Job
	 * 
	 * @return
	 */
	@RequestMapping("/refresh/all")
	public String refreshAll() {
		String result;
		try {
			initJob();
			result = "success";
		} catch (SchedulerException e) {
			log.error("refresh all jobs fail.", e);
			result = "refresh all jobs fail: " + e.getMessage();
		}
		return "refresh all jobs : " + result;
	}
	
	/**
	 * 初始化Job
	 * 
	 * @throws SchedulerException
	 */
	private void initJob() throws SchedulerException {
		List<JobInfoPO> list = jobService.queryAllJobs();
		if(list == null) {
			return;
		}
		for (JobInfoPO job : list) {
			initJob(job);
		}
	}
	
	private boolean initJob(JobInfoPO po) throws SchedulerException {
		Scheduler schediler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = new JobKey(po.getName_(), po.getGroup_());
		TriggerKey triggerKey = new TriggerKey(po.getName_(), po.getGroup_());
		Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobKey.getName(), jobKey.getGroup())
				.withSchedule(CronScheduleBuilder.cronSchedule(po.getCron_())).build();
		schediler.unscheduleJob(triggerKey);
		schediler.deleteJob(jobKey);
		if(!"OPEN".equals(po.getStatus_())) {
			return false;
		}
		
		JobDataMap map = initJobDataMap(po);
		Class<? extends CommonJob> jobClass = null;
		if("1".equals(po.getConcurrent_())) {
			jobClass = DisallowConcurrentJob.class;
		}else{
			jobClass = ConcurrentJob.class;
		}
		JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).withDescription(po.getDescription_())
				.setJobData(map).storeDurably().build();
		schediler.scheduleJob(jobDetail, trigger);
		
		return true;
	}
	
	private JobDataMap initJobDataMap(JobInfoPO po) {
		JobDataMap map = new JobDataMap();
		map.put(CommonJob.EXEC_SERVICE, po.getGroup_());
		map.put(CommonJob.EXEC_METHOD, po.getName_());
		map.put(CommonJob.EXEC_PARAMETER_, po.getParameter_());
		return map;
	}
}
